package com.joysuch.wwyt.alert.trigger;

import cn.zlg.common.enums.BusinessTypeEnum;
import cn.zlg.common.util.CollectionUtils;
import com.google.common.base.Splitter;
import com.google.gson.reflect.TypeToken;
import com.joysuch.wwyt.alert.AlertListenerConfig;
import com.joysuch.wwyt.alert.entity.NoticeWaitingTriggerList;
import com.joysuch.wwyt.alert.enums.GeTuiPartnerTypeEnum;
import com.joysuch.wwyt.alert.enums.TriggerStatusEnum;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.util.GsonUtils;
import com.joysuch.wwyt.workflow.bean.notice.TransformedUserGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ProcessNoticeWaitingListTrigger {

    private static final Logger logger = LoggerFactory.getLogger(ProcessNoticeWaitingListTrigger.class);

    private static volatile boolean toStop;

    private static final ProcessNoticeWaitingListTrigger instance = new ProcessNoticeWaitingListTrigger();

    public static ProcessNoticeWaitingListTrigger getInstance() {
        return instance;
    }

    private Thread triggerThread;

    /**
     * 开始任务
     */
    public void start() {
        triggerThread = new Thread(() -> {
            while (!toStop) {
                Connection conn = null;
                Boolean connAutoCommit = null;
                PreparedStatement preparedStatement = null;
                try {
                    conn = AlertListenerConfig.getAlertConfig().getDataSource().getConnection();
                    connAutoCommit = conn.getAutoCommit();
                    conn.setAutoCommit(false);
                    preparedStatement = conn.prepareStatement("select * from job_lock where lock_name = 'schedule_lock' for update");
                    preparedStatement.execute();
                    List<NoticeWaitingTriggerList> waitingTriggers =
                            AlertListenerConfig.getAlertConfig().getNoticeWaitingTriggerListService().getNotTriggered();
                    for (NoticeWaitingTriggerList waitingTrigger : waitingTriggers) {
                        boolean isSuccess = false;
                        Set<Long> userIds = getUserIds(waitingTrigger.getNoticeUserGroup());
                        if (CollectionUtils.isNotEmpty(userIds)) {
                            boolean buildName = false;
                            Integer businessType = waitingTrigger.getBusinessType();
                            // 如果业务类型为考试培训或者流程待办，则要在消息内容中加入用户真实姓名。
                            if ((BusinessTypeEnum.FLOW.getBusinessCode().equals(businessType) || BusinessTypeEnum.EDUCATION_TRAINING.getBusinessCode().equals(businessType))){
                                buildName = true;
                            }
                            isSuccess = AlertListenerConfig.getAlertConfig().getAlertMessageService().pushSingleBatchCid(userIds, waitingTrigger.getNoticeTitle(), waitingTrigger.getNoticeContent(), waitingTrigger.getId(), buildName);
                        }
                        String status = isSuccess ? TriggerStatusEnum.TRIGGERED_SUCCESS.getStatus() : TriggerStatusEnum.TRIGGERED_FAIL.getStatus();
                        AlertListenerConfig.getAlertConfig().getNoticeWaitingTriggerListService().updateById(waitingTrigger.setTriggerStatus(status));
                    }
                } catch (Exception e) {
                    if (!toStop) {
                        logger.error("ProcessNoticeWaitingTrigger Exception:", e);
                    }
                } finally {
                    // commit
                    if (conn != null) {
                        try {
                            conn.commit();
                        } catch (SQLException e) {
                            if (!toStop) {
                                logger.error(e.getMessage(), e);
                            }
                        }
                        try {
                            conn.setAutoCommit(connAutoCommit);
                        } catch (SQLException e) {
                            if (!toStop) {
                                logger.error(e.getMessage(), e);
                            }
                        }
                        try {
                            conn.close();
                        } catch (SQLException e) {
                            if (!toStop) {
                                logger.error(e.getMessage(), e);
                            }
                        }
                    }
                    // close PreparedStatement
                    if (null != preparedStatement) {
                        try {
                            preparedStatement.close();
                        } catch (SQLException e) {
                            if (!toStop) {
                                logger.error(e.getMessage(), e);
                            }
                        }
                    }
                }
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    logger.error("ProcessNoticeWaitingListTrigger thread sleep error:", e);
                }
            }
            logger.info("ProcessNoticeWaitingTrigger thread stop");
        });
        triggerThread.setName("ProcessNoticeWaitingTrigger");
        triggerThread.setDaemon(true);
        triggerThread.start();
    }

    /**
     * 停止任务
     */
    public void toStop() {
        toStop = true;
        triggerThread.interrupt();
        try {
            triggerThread.join();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 传入参与对象，返回所有参与用户的别名集合
     *
     * @param noticeUserGroup:json串， 键为参与者类型（用户，部门，岗位），
     *                               值为参与者的id，有多个参与者时以","连接
     */
    public Set<Long> getUserIds(String noticeUserGroup) {
        Set<Long> userIds = new HashSet<>();
        List<TransformedUserGroup> valList = GsonUtils.fromJson(noticeUserGroup, new TypeToken<List<TransformedUserGroup>>() {
        }.getType());
        valList.forEach(each -> {
            if (GeTuiPartnerTypeEnum.PERSON.getType().equals(each.getKey())) {
                List<String> userIdsStr = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(each.getValue());
                for (String idStr : userIdsStr) {
                    userIds.add(Long.parseLong(idStr));
                }
            }
            if (GeTuiPartnerTypeEnum.JOB.getType().equals((each.getKey()))) {
                List<String> jobIds = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(each.getValue());
                for (String s : jobIds) {
                    userIds.addAll(AlertListenerConfig.getAlertConfig().getBaseUserDao().findIdByJob(Long.parseLong(s)));
                }
            }
            if (GeTuiPartnerTypeEnum.DEPARTMENT.getType().equals((each.getKey()))) {
                List<String> departIds = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(each.getValue());
                for (String s : departIds) {
                    userIds.addAll(AlertListenerConfig.getAlertConfig().getBaseUserDao().findIdByDepartId(Long.parseLong(s)));
                }
            }
            if (GeTuiPartnerTypeEnum.ROLE.getType().equals((each.getKey()))) {
                List<String> roleIds = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(each.getValue());
                for (String s : roleIds) {
                    userIds.addAll(AlertListenerConfig.getAlertConfig().getBaseUserDao().findRoleUserListAll(Long.parseLong(s)));
                }
            }
        });
        return userIds;
    }
}